package com.netkit;

import com.netkit.event.NetkitChannelEventListener;
import com.netkit.event.NetkitSessionListener;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jboss.netty.channel.Channel;

public class NetkitContext
{
  private static final long DefaultSessionTimeout = 120000L;
  private final Map<Integer, Class<Action>> registedActions = new ConcurrentHashMap();
  private final List<ActionFilter> actionFilters = new LinkedList();
  private final Map<String, Object> attributes = new ConcurrentHashMap();
  private final SessionGroup sessionGroup = new SessionGroup();
  private NetkitChannelEventListener channelEventListener = null;
  private NetkitSessionListener sessionOnCreate = null;
  private NetkitSessionListener sessionOnClose = null;
  private long sessionTimeout = 120000L;
  private int maxConnections = 100000;
  private ExecutorService bossExecutor;
  private ExecutorService workerExecutor;

  public void setBossExecutor(ExecutorService bossExecutor)
  {
    this.bossExecutor = bossExecutor;
  }

  public void setWorkerExecutor(ExecutorService workerExecutor) {
    this.workerExecutor = workerExecutor;
  }

  public ExecutorService getBossExecutor() {
    if (this.bossExecutor == null) {
      this.bossExecutor = Executors.newCachedThreadPool();
    }
    return this.bossExecutor;
  }

  public ExecutorService getWorkerExecutor() {
    if (this.workerExecutor == null) {
      this.workerExecutor = Executors.newCachedThreadPool();
    }
    return this.workerExecutor;
  }

  public void setSessionTimeout(long millis)
  {
    this.sessionTimeout = millis;
  }

  public long getSessionTimeout() {
    return this.sessionTimeout;
  }

  public void addActionFilter(ActionFilter filter) {
    if (filter == null) throw new NullPointerException("action filter object was null.");
    this.actionFilters.add(filter);
  }

  public int getSessionSize() {
    return this.sessionGroup.size();
  }

  public List<ActionFilter> getActionFilterList() {
    return Collections.unmodifiableList(this.actionFilters);
  }

  public void registerAction(int functionId, Class claxx)
  {
    synchronized (this.registedActions) {
      Class clazz = (Class)this.registedActions.get(Integer.valueOf(functionId));
      if (clazz != null) {
        this.registedActions.remove(Integer.valueOf(functionId));
      }
      this.registedActions.put(Integer.valueOf(functionId), claxx);
    }
  }

  public Class<Action> lookupRegisteredAction(int functionId) {
    Class clazz = (Class)this.registedActions.get(Integer.valueOf(functionId));
    return clazz;
  }

  public void setChannelEventListener(NetkitChannelEventListener eventListener) {
    this.channelEventListener = eventListener;
  }

  public NetkitChannelEventListener getChannelEventListener() {
    return this.channelEventListener;
  }

  public NetkitSessionListener getSessionOnCreatedEventListener()
  {
    return this.sessionOnCreate;
  }

  public void setSessionOnCreatedEventListener(NetkitSessionListener listener) {
    this.sessionOnCreate = listener;
  }

  public NetkitSessionListener getSessionOnClosedEventListener()
  {
    return this.sessionOnClose;
  }

  public void setSessionOnClosedEventListener(NetkitSessionListener listener) {
    this.sessionOnClose = listener;
  }

  public Session getSession(Channel channel) {
    return getSession(channel.getId().intValue());
  }

  public Session getSession(int sessionId) {
    return this.sessionGroup.get(Integer.valueOf(sessionId));
  }

  protected Session createSession(Channel channel) {
    if (channel == null) return null;
    Session session = getSession(channel);
    if (session != null) {
      session.setOnCreatedEventListener(this.sessionOnCreate);
      session.setOnClosedEventListener(this.sessionOnClose);
      return session;
    }
    Session s = new Session(this, channel);
    s.setOnCreatedEventListener(this.sessionOnCreate);
    s.setOnClosedEventListener(this.sessionOnClose);
    this.sessionGroup.add(Integer.valueOf(s.getSessionId()), s);
    return s;
  }

  protected Session createSession(Channel channel, NetkitSessionListener onCreatedListener, NetkitSessionListener onClosedListener) {
    this.sessionOnCreate = onCreatedListener;
    this.sessionOnClose = onClosedListener;
    return createSession(channel);
  }

  public Collection<Session> getAllSessions() {
    return this.sessionGroup.sessions();
  }

  public void release() {
    this.sessionGroup.close();
    this.bossExecutor.shutdownNow();
    this.workerExecutor.shutdownNow();
  }

  public int getMaxConnections() {
    return this.maxConnections;
  }

  public void setMaxConnections(int maxConnections) {
    this.maxConnections = maxConnections;
  }

  public void setAttribute(String key, Object value) {
    this.attributes.put(key, value);
  }

  public Object getAttribute(String key) {
    return this.attributes.get(key);
  }

  public Map<String, Object> getAttributes() {
    return this.attributes;
  }
}